(function($) {

    $.fn.tagcloud = function(options) {
      var opts = $.extend({}, $.fn.tagcloud.defaults, options);
      tagWeights = this.map(function(){
        return $(this).attr("rel");
      });
      tagWeights = jQuery.makeArray(tagWeights).sort(compareWeights);
      lowest = tagWeights[0];
      highest = tagWeights.pop();
      range = highest - lowest;
      if(range === 0) {range = 1;}
      // Sizes
      if (opts.size) {
        fontIncr = (opts.size.end - opts.size.start)/range;
      }
      // Colors
      if (opts.color) {
        colorIncr = colorIncrement (opts.color, range);
      }
      return this.each(function() {
        weighting = $(this).attr("rel") - lowest;
        if (opts.size) {
          $(this).css({"font-size": opts.size.start + (weighting * fontIncr) + opts.size.unit});
        }
        if (opts.color) {
          // change color to background-color
          $(this).css({"backgroundColor": tagColor(opts.color, colorIncr, weighting)});
        }
      });
    };
  
    $.fn.tagcloud.defaults = {
      size: {start: 14, end: 18, unit: "pt"}
    };
  
    // Converts hex to an RGB array
    function toRGB (code) {
      if (code.length == 4) {
        code = jQuery.map(/\w+/.exec(code), function(el) {return el + el; }).join("");
      }
      hex = /(\w{2})(\w{2})(\w{2})/.exec(code);
      return [parseInt(hex[1], 16), parseInt(hex[2], 16), parseInt(hex[3], 16)];
    }
  
    // Converts an RGB array to hex
    function toHex (ary) {
      return "#" + jQuery.map(ary, function(i) {
        hex =  i.toString(16);
        hex = (hex.length == 1) ? "0" + hex : hex;
        return hex;
      }).join("");
    }
  
    function colorIncrement (color, range) {
      return jQuery.map(toRGB(color.end), function(n, i) {
        return (n - toRGB(color.start)[i])/range;
      });
    }
  
    function tagColor (color, increment, weighting) {
      rgb = jQuery.map(toRGB(color.start), function(n, i) {
        ref = Math.round(n + (increment[i] * weighting));
        if (ref > 255) {
          ref = 255;
        } else {
          if (ref < 0) {
            ref = 0;
          }
        }
        return ref;
      });
      return toHex(rgb);
    }
  
    function compareWeights(a, b)
    {
      return a - b;
    }
  
  })(jQuery);
  